#!/bin/bash
#-----------------------------------------------------------
# Module    : screen
# Location  : */lib/bfw/src
# Author    : Scott Smith <scott@bashify.com>
# Purpose   : Ncurses functions for use with bash.
# Copyright (c) 2005-2013 Scott Smith <scott@bashify.com>
#-----------------------------------------------------------
# NOTES
#-----------------------------------------------------------
# If the COLUMNS variable is set, it can cause problems in
# the 'cursor columns' function. IT IS A GOOD IDEA TO 'UNSET
# COLUMNS' IN THE CALLING PROGRAM (not done here as that is
# not safe to do in a library.)
#-----------------------------------------------------------
# CHANGELOG
#-----------------------------------------------------------
# $Log$
# * Thu May 16 2013 Scott Smith <scott@bashify.com>
# - Initial release.
#-----------------------------------------------------------

#-----------------------------------------------------------

if [ -z "bfw_bash_framework" ]
then
  echo "error: bfw scripts cannot be run directly"
  exit 99
fi

#-----------------------------------------------------------

[[ "$TERM" =~ xterm ]] || echo "WARNING: unsupported terminal $TERM" 1>&2

#-----------------------------------------------------------
# handle screen color/display modes

color()
{
    local MODE=setf
    while [ "$1" ]
    do
        case "$1" in
        normal)
            tput sgr0
            ;;
        reverse)
            case "$2" in
            off) tput sgr0 ; shift ;;
            on) tput rev ; shift ;;
            *) tput rev
            esac
            ;;
        bold|bright)
            case "$2" in
            off) tput dim ; shift ;;
            on) tput bold ; shift ;;
            *) tput bold ;;
            esac
            ;;
        dim)
            case "$2" in
            off) shift ;;
            on) tput dim ; shift ;;
            *) tput dim ;;
            esac
            ;;
        fore|foreground|fgnd)
            MODE="setf"
            ;;
        on|back|background|bgnd)
            MODE="setb"
            ;;
        black)
            tput $MODE 0
            ;;
        blue)
            tput $MODE 1
            ;;
        green)
            tput $MODE 2
            ;;
        cyan)
            tput $MODE 3
            ;;
        red)
            tput $MODE 4
            ;;
        magenta)
            tput $MODE 5
            ;;
        yellow)
            tput $MODE 6
            ;;
        white)
            tput $MODE 7
            ;;
        standout)
            case "$2" in
            off) tput rmso ; shift ;;
            on) tput smso ; shift ;;
            *) tput smso ;;
            esac
            ;;
        underline)
            case "$2" in
            off) tput rmul ; shift ;;
            on) tput smul ; shift ;;
            *) tput smul ;;
            esac
            ;;
        esac
        shift
    done
}
declare -Ftx color

#-----------------------------------------------------------
# handle cursor positioning and attributes

cursor()
{
    local CSRPOS
    case "$1" in
    [0-9]|[1-9][0-9]) tput cup "${1:-0}" "${2:-0}" ;;
    goto) tput cup "${2:-0}" "${3:-0}" ;;
    home) tput cup 0 0 ;;
    push) tput sc ;;
    pop) tput rc ;;
    recall) tput rc ; sleep 0.1; tput sc ;;
    rows) tput lines ;;
    columns) tput cols ;;
    left) tput cub "${2:-1}" ;;
    right) tput cuf "${2:-1}" ;;
    up) tput cuu "${2:-1}" ;;
    down) tput cud "${2:-1}" ;;
    on) tput cnorm ;;
    off) tput civis ;;
    setpos) tput cup "${2%;*}" "${2#*;}" ;;
    pos|position)
        tput u7
        read -sdR CSRPOS
        export "${2:-SCREEN_POS}"="$(cut -d'[' -f2 <<<"$CSRPOS")"
        ;;
    row|rowpos)
        tput u7
        read -sdR CSRPOS
        export "${2:-SCREEN_ROW}"="$(cut -d'[' -f2 <<<"$CSRPOS" | cut -d';' -f1)"
        ;;
    col|colpos)
        tput u7
        read -sdR CSRPOS
        export "${2:-SCREEN_COL}"="$(cut -d'[' -f2 <<<"$CSRPOS" | cut -d';' -f2)"
        ;;
    esac
}
declare -Ftx cursor

#-----------------------------------------------------------
# handle screen clear/insert

clear()
{
    case "$1" in
    ""|scr|screen) tput clear ;;
    eos|end-of-screen) tput ed ;;
    eol|end-of-line) tput el ;;
    bol|beginning-of-line) tput el1 ;;
    chr|char|character) tput ech "${2:-1}" ;;
    chrs|chars|characters) tput ech "${2:-1}" ;;
    del|delete)
         case "$2" in
         chr|char|character) tput dch "${3:-1}" ;;
         chrs|chars|characters) tput dch "${3:-1}" ;;
         line|lines) tput dl "${3:-1}" ;;
         esac
         ;;
    ins|insert)
         case "$2" in
         chr|char|character) tput ich "${3:-1}" ;;
         chrs|chars|characters) tput ich "${3:-1}" ;;
         line|lines) tput il "${3:-1}" ;;
         esac
         ;;
    esac
}
declare -Ftx clear

#-----------------------------------------------------------
# terminal window modifiers - xterm compatible

terminal()
{
  case "$1" in
  size) printf "\033[8;${2};${3}t" ;;
  title) printf "\033]0;${2}\007" ;;
  window-title) printf "\033]1;${2}\007" ;;
  icon-title) printf "\033]2;${2}\007" ;;
  *) : ;;
  esac
}

#-----------------------------------------------------------
# create a buffer using supplied string that is the size of
# the current display width

makebuffer()
{
    local str="$*"
    local strsize="${#str}"
    local scrsize="$(tput cols)"
    local repeat=$(( (scrsize / strsize) + 1 ))
    local buffer=""
    local n
    for (( n=1; n<=repeat; n++ ))
    do
        buffer+="$str"
    done
    echo -n "${buffer:0:$scrsize}"
}

#-----------------------------------------------------------
# add left/right elements to a buffer (usually a header)

leftright()
{
    local brackets="$1"
    local left_bracket=""
    local right_bracket=""

    case "$brackets" in
    --bracket|--brackets)  left_bracket="[ " ; right_bracket=" ]" ; shift ;;
    --brace|--brackes)     left_bracket="{ " ; right_bracket=" }" ; shift ;;
    --paren|--parentheses) left_bracket="( " ; right_bracket=" )" ; shift ;;
    --angle|--angles)      left_bracket="< " ; right_bracket=" >" ; shift ;;
    --hash|--hashes)       left_bracket="# " ; right_bracket=" #" ; shift ;;
    --bar|--bars)          left_bracket="| " ; right_bracket=" |" ; shift ;;
    --) shift ;;
    *) brackets="--" ;;
    esac

    local left="$left_bracket${1}$right_bracket"
    local right="$left_bracket${2}$right_bracket"
    local buffer="$(makebuffer "${3:- }")"

    local left_size="${#left}"
    local right_size="${#right}"
    local buffer_size="${#buffer}"
    local filler="${buffer:$left_size:$(( buffer_size - left_size - right_size ))}"
    echo -n "$left$filler$right"
}
declare -Ftx leftright

#-----------------------------------------------------------
# center a string in the default (80 chr) or provided buffer

center()
{
    local brackets="$1"
    local left_bracket=""
    local right_bracket=""

    case "$brackets" in
    --bracket|--brackets)  left_bracket="[ " ; right_bracket=" ]" ; shift ;;
    --brace|--brackes)     left_bracket="{ " ; right_bracket=" }" ; shift ;;
    --paren|--parentheses) left_bracket="( " ; right_bracket=" )" ; shift ;;
    --angle|--angles)      left_bracket="< " ; right_bracket=" >" ; shift ;;
    --hash|--hashes)       left_bracket="# " ; right_bracket=" #" ; shift ;;
    --bar|--bars)          left_bracket="| " ; right_bracket=" |" ; shift ;;
    --) shift ;;
    *) brackets="--" ;;
    esac

    local text="$left_bracket${1}$right_bracket"
    local buffer="$(makebuffer "${2:- }")"

    local length=${#text}
    local width=${#buffer}
    local left=$(( ( width - length ) / 2 ))
    local right=$(( width - length - left ))
    local rstart=$(( left + length ))
    local result

    echo -n "${buffer:0:$left}$text${buffer:$rstart:$width}"
}
declare -Ftx center

#-----------------------------------------------------------
leftcenterright()
{
    local brackets="$1"
    local left_bracket=""
    local right_bracket=""

    case "$brackets" in
    --bracket|--brackets)  shift ;;
    --brace|--brackes)     shift ;;
    --paren|--parentheses) shift ;;
    --angle|--angles)      shift ;;
    --hash|--hashes)       shift ;;
    --bar|--bars)          shift ;;
    --) shift ;;
    *) brackets="--" ;;
    esac

    local left="$1"
    local center="$2"
    local right="$3"
    local buffer="$(makebuffer "${4:- }")"

    buffer="$(leftright "$brackets" "$left" "$right" "$buffer")"

    center "$brackets" "$center" "$buffer"
}

#-----------------------------------------------------------
# output a screen header, formatted [date header time]

screen_header()
{
    local header="$*"
    local clock="$(date +%r)"
    #clear screen
    #color bold
    leftcenterright "$(date '+%D')" "${header:-$_SCREEN_TITLE}" "${clock/??? / }"
    screen_dline
    #color normal
}
declare -Ftx screen_header

#-----------------------------------------------------------
# output a screen footer, formatted [helpinfo footer version]

screen_footer()
{
    local footer="$*"
    local clock="$(date +%r)"
    local helpinfo="${_SCREEN_HELPINFO:-$PROG}"
    local version="${_SCREEN_VERSION:-$USER}"
    #clear screen
    #color bold
    screen_dline
    leftcenterright "$helpinfo" "$footer" "$version"
    #color normal
}
declare -Ftx screen_footer

#-----------------------------------------------------------
# output a blank line

screen_bline()
{
    makebuffer ' '
}
declare -Ftx screen_bline

#-----------------------------------------------------------
# output a double line

screen_dline()
{
    makebuffer '='
}
declare -Ftx screen_dline

#-----------------------------------------------------------
# output a single line

screen_sline()
{
    makebuffer '-'
}
declare -Ftx screen_sline

#-----------------------------------------------------------
# errmsg function (since we know we have color)

errmsg()
{
  local KBD
  color normal bold white on red
  echo -en "$2"
  color normal
  read -t 3 KBD
  echo
  die "$1" "$3"
}
declare -Ftx errmsg

#-----------------------------------------------------------
#EOF(screen)
